package com.xl.basic.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xl.basic.entity.Result;
import com.xl.basic.entity.ResultEnums;
import com.xl.basic.entity.param.LoginByPasswordParam;
import com.xl.basic.entity.result.LoginResult;
import com.xl.basic.entity.result.TokenResult;
import com.xl.basic.entity.UserInfo;
import com.xl.basic.service.LoginService;
import com.xl.basic.utils.LoginUtils;
import com.xl.dao.domain.XlUser;
import com.xl.dao.mapper.XlUserMapper;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.service.WxOAuth2Service;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * @author 钟勇
 * Create in 2023/8/24 16:44
 */
@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    private final XlUserMapper userMapper;
    private final WxMpService wxMpService;

    @Override
    public Result<LoginResult> loginByPassword(@NonNull LoginByPasswordParam param) {
        String pwdEnc = LoginUtils.encryptPassword(param.getPassword());

        XlUser userInfo = userMapper.selectOne(new LambdaQueryWrapper<XlUser>()
                .eq(XlUser::getState, 1)
                .and(w -> {
                    w.eq(XlUser::getPhone, param.getLoginId())
                            .or()
                            .eq(XlUser::getEmail, param.getLoginId());
                })
                .eq(XlUser::getPassword, pwdEnc)
                .last("LIMIT 1")
        );

        if (userInfo == null) {
            return ResultEnums.BusinessError.getResult("登录失败");
        }

        if (userInfo.getDisableFlag().equals(1)) {
            return ResultEnums.BusinessError.getResult("您的账号已被禁用，请联系管理员");
        }

        //向系统中写入用户信息
        LoginUtils.setUserInfo(BeanUtil.copyProperties(userInfo, UserInfo.class));

        //生成token
        String userId = userInfo.getUserId();
        TokenResult tokenInfo = LoginUtils.generateToken(userId);

        return ResultEnums.Success.getDataResult(new LoginResult(userId, tokenInfo.getToken(), tokenInfo.getExpires()));
    }

    @Override
    public Result<LoginResult> loginByWxCode(@NonNull String code) {
        try {
            WxOAuth2Service oAuth2Service = wxMpService.getOAuth2Service();
            WxOAuth2AccessToken wxOAuth2AccessToken = oAuth2Service.getAccessToken(code);
            if (wxOAuth2AccessToken == null || StrUtil.isBlank(wxOAuth2AccessToken.getOpenId())) {
                return ResultEnums.ParamError.getResult("code转换失败");
            }

            String openId = wxOAuth2AccessToken.getOpenId();

            XlUser userInfo = userMapper.selectOne(new LambdaQueryWrapper<XlUser>()
                    .eq(XlUser::getState, 1)
                    .eq(XlUser::getOpenId, openId)
                    .last("LIMIT 1")
            );

            if (userInfo == null) {
                userInfo = new XlUser()
                        .setOpenId(openId)
                        .setState(1)
                        .setDisableFlag(0)
                        .setAddTime(LocalDateTime.now());

                if (userMapper.insert(userInfo) == 0) {
                    return ResultEnums.Exception.getResult("用户信息写入失败");
                }
            } else {
                if (userInfo.getDisableFlag().equals(1)) {
                    return ResultEnums.BusinessError.getResult("您的账号已被禁用，请联系管理员");
                }
            }

            WxOAuth2UserInfo wxUserInfo = null;
            try {
                wxUserInfo = oAuth2Service.getUserInfo(wxOAuth2AccessToken, null);
            } catch (WxErrorException ignored) {

            }

            if (wxUserInfo != null) {
                if (StrUtil.isBlank(userInfo.getUserName())) {
                    userInfo.setUserName(wxUserInfo.getNickname());
                }

                if (StrUtil.isBlank(userInfo.getAvatarUrl())) {
                    userInfo.setAvatarUrl(wxUserInfo.getHeadImgUrl());
                }
            }


            //向系统中写入用户信息
            LoginUtils.setUserInfo(BeanUtil.copyProperties(userInfo, UserInfo.class));

            //生成token
            String userId = userInfo.getUserId();
            TokenResult tokenInfo = LoginUtils.generateToken(userId);

            return ResultEnums.Success.getDataResult(new LoginResult(userId, tokenInfo.getToken(), tokenInfo.getExpires()));


        } catch (WxErrorException e) {
            return ResultEnums.Exception.getResult(e.toString());
        }
    }

    @Override
    public Result<UserInfo> getUserInfo(@NonNull String userId) {
        XlUser user = userMapper.selectById(userId);
        if (user == null || user.getState() != 1) {
            return ResultEnums.BusinessError.getResult("未找到用户信息");
        }

        if (user.getDisableFlag().equals(1)) {
            return ResultEnums.BusinessError.getResult("您的账号已被禁用，请联系管理员");
        }

        return ResultEnums.Success.getDataResult(BeanUtil.copyProperties(user, UserInfo.class));
    }
}
